package com.yeyks.controller;

import com.alibaba.fastjson.JSON;
import com.yeyks.dal.dao.AccountInfoMapper;
import com.yeyks.dal.dao.CompanyInfoMapper;
import com.yeyks.dal.dao.HotelInfoMapper;
import com.yeyks.dal.dao.RoomInfoMapper;
import com.yeyks.dal.domain.AccountInfo;
import com.yeyks.dal.domain.HotelInfo;
import com.yeyks.dal.domain.RoomInfo;
import com.yeyks.exception.PermissionInvalidException;
import com.yeyks.exception.TokenInvalidException;
import com.yeyks.model.Ajax.AjaxResponseBody;
import com.yeyks.model.PreOrderInfo;
import com.yeyks.model.UserHotelSearchHotelInfo;
import com.yeyks.model.UserHotelSearchIdInfo;
import com.yeyks.model.UserHotelSearchRoomInfo;
import com.yeyks.model.em.AccountType;
import com.yeyks.model.em.ResponseStatus;
import com.yeyks.service.AccountService;
import com.yeyks.model.Ajax.AjaxResponseBody;
import com.yeyks.model.UserHotelSearchHotelInfo;
import com.yeyks.model.UserHotelSearchRoomInfo;
import com.yeyks.model.em.ResponseStatus;
import com.yeyks.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.Min;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

@RestController
@RequestMapping(value = "/ajax/hotel")
public class HotelPreOrderController {

    @Autowired
    HotelInfoMapper hotelInfoMapper;

    @Autowired
    AccountInfoMapper accountInfoMapper;

    @Autowired
    CompanyInfoMapper companyInfoMapper;

    @Autowired
    RoomInfoMapper roomInfoMapper;

    @Autowired
    AccountService accountService;

//    @Autowired
//    private SimpMessagingTemplate messagingTemplate;

    @ApiIgnore
    @RequestMapping(value = "/userSearch", method = RequestMethod.POST)
    public ResponseEntity<?> userSearch(
            HttpServletRequest request, HttpServletResponse response,
            @RequestParam(name = "token", defaultValue = "", required = true) String token, // Token，暂时不用
            @RequestParam(name = "city", defaultValue = "", required = true) String city, // 城市名称，例：北京
            @RequestParam(name = "addr", defaultValue = "", required = true) String addr, // 街道地址，可不填，例：十里堡
            @RequestParam(name = "checkIn", defaultValue = "", required = true) String checkIn, // check-in日期，字符串描述，没有时间部分，例：2018-08-13
            @RequestParam(name = "checkOut", defaultValue = "", required = true) String checkOut, // check-out日期，字符串描述，没有时间部分，例：2018-08-16
            @RequestParam(name = "price", defaultValue = "0", required = true) Integer price, // 价格（单位：分），默认值（0不限价），例：20000 （200元）
            @RequestParam(name = "starLevel", defaultValue = "0", required = true) Integer starLevel, // 星级：默认全部（0），1民宿，2三星，3四星，4五星，5商务
            @RequestParam(name = "order", defaultValue = "0", required = true) Integer order, // 推荐(排序)模式：order 0智能排序（默认是这个），1距离 2价格
            @RequestParam(name = "pageNum", defaultValue = "0", required = true) Integer pageNum, // 页号
            @RequestParam(name = "pageCount", defaultValue = "0", required = true) Integer pageCount, // 每页条目数（条目数为房间总量）
            @RequestParam(name = "positionX", defaultValue = "", required = true) Double positionX, // 经度值，可不填
            @RequestParam(name = "positionY", defaultValue = "", required = true) Double positionY // 纬度值，可不填
    ) {
        AjaxResponseBody responseBody = new AjaxResponseBody();

        try {
            if (city.isEmpty() ||
                    checkIn.isEmpty() || checkOut.isEmpty() ||
                    price == 0) {
                responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_PARAMETERS.getCode());
                responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_PARAMETERS.getMsg());
            } else {
                if (starLevel == 0 || starLevel == 1) {
                    starLevel = null;
                }

                List<Map> idInfoList = hotelInfoMapper.selectByUser(
                        price, city, addr, starLevel,
                        checkIn, checkOut,
                        positionX, positionY,
                        null, null,
                        null
                );

                Integer offset = null, maxrow = null;
                if (pageNum != 0 && pageCount != 0) {
                    offset = (pageNum - 1) * pageCount;
                    maxrow = pageCount;
                }

                if (idInfoList != null && idInfoList.size() != 0) {
                    /////////////////////////////////////////////////////////////////
                    // 获得酒店信息
                    Set<Integer> ids = new HashSet<>();
                    for (Map res : idInfoList) {
                        ids.add(((Long) res.get("hotel_id")).intValue());
                    }
                    List<HotelInfo> hotelInfos = hotelInfoMapper.selectByIds(new ArrayList<Integer>(ids));

                    // 获得酒店信息
                    ids.clear();
                    for (Map res : idInfoList) {
                        ids.add(((Long) res.get("room_id")).intValue());
                    }
                    List<RoomInfo> roomInfos = roomInfoMapper.selectByIds(new ArrayList<Integer>(ids));
                    /////////////////////////////////////////////////////////////////

                    List<UserHotelSearchHotelInfo> allHotelInfoList = new ArrayList<>();
                    for(HotelInfo hotelInfo : hotelInfos) {
                        UserHotelSearchHotelInfo hotel = new UserHotelSearchHotelInfo();

                        for (Map res : idInfoList) {
                            int hotelId = ((Long) res.get("hotel_id")).intValue();
                            int roomId = ((Long) res.get("room_id")).intValue();
                            int availableRooms = ((BigDecimal) res.get("available_rooms")).intValue();
                            if (hotelId == hotelInfo.getId().intValue()) {

                                // 更新距离
                                if (hotel.getDistance() == null) {
                                    try {
                                        Double distance = Double.parseDouble(res.get("hotel_distance").toString());
                                        hotel.setDistance(distance.intValue());
                                    } catch (Throwable e) {
                                        hotel.setDistance(null);
                                    }
                                }

                                for (RoomInfo roomInfo : roomInfos) {
                                    if (roomInfo.getId() == roomId) {
                                        UserHotelSearchRoomInfo room = new UserHotelSearchRoomInfo();
                                        room.setRoomInfo(roomInfo);
                                        room.setAvailable(availableRooms);

                                        hotel.getRoom().add(room);
                                    }
                                }
                            }
                        }

                        hotel.setHotelInfo(hotelInfo);
                        allHotelInfoList.add(hotel);
                    }

                    // 排序
                    if (order == 2) {
                        // 距离排序
                        allHotelInfoList.sort(new Comparator<UserHotelSearchHotelInfo>() {
                            @Override
                            public int compare(UserHotelSearchHotelInfo o1, UserHotelSearchHotelInfo o2) {
                                return (o1.getDistance() == null ? 0 : o1.getDistance()) -
                                        (o2.getDistance() == null ? 0 : o2.getDistance());
                            }
                        });
                    } else if (order == 3) {
                        // 价格排序
                        allHotelInfoList.sort(new Comparator<UserHotelSearchHotelInfo>() {
                            @Override
                            public int compare(UserHotelSearchHotelInfo o1, UserHotelSearchHotelInfo o2) {
                                Integer p1 = Integer.MAX_VALUE;
                                for (UserHotelSearchRoomInfo roomInfo : o1.getRoom()) {
                                    try {
                                        if (roomInfo.getRoomInfo().getCurPrice() < p1) {
                                            p1 = roomInfo.getRoomInfo().getCurPrice();
                                        }
                                    } catch (Throwable e) {e.printStackTrace();}
                                }

                                Integer p2 = Integer.MAX_VALUE;
                                for (UserHotelSearchRoomInfo roomInfo : o2.getRoom()) {
                                    try {
                                        if (roomInfo.getRoomInfo().getCurPrice() < p2) {
                                            p2 = roomInfo.getRoomInfo().getCurPrice();
                                        }
                                    } catch (Throwable e) {e.printStackTrace();}
                                }

                                return p1 - p2;
                            }
                        });
                    } else {
                        // 智能排序
                        allHotelInfoList.sort(new Comparator<UserHotelSearchHotelInfo>() {
                            @Override
                            public int compare(UserHotelSearchHotelInfo o1, UserHotelSearchHotelInfo o2) {
                                return - (
                                        ((o1.getHotelInfo() == null || o1.getHotelInfo().getScore() == null) ? 0 : o1.getHotelInfo().getScore())
                                        -
                                        ((o2.getHotelInfo() == null || o2.getHotelInfo().getScore() == null) ? 0 : o2.getHotelInfo().getScore())
                                );
                            }
                        });
                    }

                    /////////////////////////////////////////////////////////////////
                    // 分页
                    if (offset == null || maxrow == null) {
                        offset = 0;
                        maxrow = hotelInfos.size();
                    }

                    if (offset + maxrow > hotelInfos.size()) {
                        maxrow = hotelInfos.size() - offset;
                    }

                    List<UserHotelSearchHotelInfo> pageHotelList = new ArrayList<>();
                    for (int i = offset; i < offset + maxrow; ++i) {
                        pageHotelList.add(allHotelInfoList.get(i));
                    }

                    /////////////////////////////////////////////////////////////////

                    responseBody.addMapBody("count", hotelInfos.size());
                    responseBody.addMapBody("list", pageHotelList);
                } else {
                    List<HotelInfo> hotelInfos = hotelInfoMapper.selectByCity(city);
                    responseBody.addMapBody("city_result", hotelInfos == null ? 0 : hotelInfos.size());
                }

                responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
                responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
            }
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL.getMsg());
        }

        return ResponseEntity.ok(responseBody);
    }
}
